//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-4-2
// @Time:上午9:49
//

#include <assert.h>
#include <signal_protocol_internal.h>
#include "OPKManager.h"
#include "Common.h"

using namespace GeeJoan::E2EE::Common;
using namespace GeeJoan::E2EE::SDK;

bool OPKManager::createOpk_One()
{
    assert(global_context);
    int result = 0;

    // 需要释放内存
    ec_key_pair *temp_opk = 0;
    result = curve_generate_key_pair(global_context, &temp_opk);

    if (result < 0)
    {
        // 失败 直接 销毁
        if (temp_opk)ec_key_pair_destroy((signal_type_base *) temp_opk);
        return EXIT_FAILURE;
    } else
    {
        // 成功 放进map
        // 获取 公钥
        // 指针 不需要释放内存
        ec_public_key *tempPub_key = ec_key_pair_get_public(temp_opk);

        // 序列化 需要释放内存
        signal_buffer *buffer;
        int ret = ec_public_key_serialize(&buffer, tempPub_key);

        // 构造成 字符串 对象 作为 key
        std::string pubKeyStr((char *) buffer->data, buffer->len);

        // 移交到 map
        KeyPairDataType *keyPairData = new KeyPairDataType;
        ret = serialEcKeyPair(temp_opk, *keyPairData);

        // 是否成功
        if (ret == EXIT_SUCCESS)
        {
            m_opk_map.insert(std::pair<std::string, std::unique_ptr<KeyPairDataType>>(pubKeyStr,
                                                                                  std::unique_ptr<KeyPairDataType>(
                                                                                          keyPairData)));
        } else
        {
            if (keyPairData)delete keyPairData;
        }


        if (buffer) signal_buffer_free(buffer);
        if (temp_opk)ec_key_pair_destroy((signal_type_base *) temp_opk);

        return EXIT_SUCCESS;
    }
}

int OPKManager::createOpk_More(int size)
{
    int successSize = 0;
    for (int i = 0; i < size; ++i)
    {
        if (this->createOpk_One())
        {
            successSize++;
        }
    }
    return successSize;
}

std::unique_ptr<KeyPairDataType> OPKManager::getKeyPair(std::string pubkey)
{
    std::unique_ptr<KeyPairDataType> curr;
    auto iter = m_opk_map.find(pubkey);
    if (iter != m_opk_map.end())
    {
        // 交还 所有权
        curr = std::move(iter->second);

        // 消除 key
        m_opk_map.erase(iter);
    }

    return curr;
}

std::unique_ptr<KeyPairDataType> OPKManager::getAKeyPair()
{
    std::unique_ptr<KeyPairDataType> curr;
    auto iter = m_opk_map.begin();
    if (iter != m_opk_map.end())
    {
        // 交还 所有权
        curr = std::move(iter->second);

        // 消除 key
        m_opk_map.erase(iter);
    }

    return curr;
}

OPKManager::OPKManager(signal_context *globalContext) : global_context(globalContext)
{

}

